#pragma once

#define DEBUG_STRINGHASH

#ifdef DEBUG_STRINGHASH
#define CASSERT(expn) typedef char __C_ASSERT__[(expn)?1:-1] 
const char* gethashstr(uint32 key);
string*		inserthashstring(uint32 key,const char* c);
extern string* nullstr;
#endif

template<size_t N> __forceinline unsigned _Hash(const char (&str)[N]) 
{
	typedef const char (&truncated_str)[N-1]; 
	return str[N-1] + 65599 * _Hash((truncated_str)str); 
} 
template<> 
__forceinline unsigned _Hash(const char (&str)[2]) { return str[1] + 65599 * str[0]; } 

struct stringhash
{
	unsigned value;
#ifdef DEBUG_STRINGHASH
	string* str;
#endif
	stringhash()
	{
		value=0;
#ifdef DEBUG_STRINGHASH
		str=nullstr;
#endif
	}
	template <size_t N> __forceinline stringhash(const char (&str)[N])
	{
		CASSERT(N<62);
		value=_Hash(str);
#ifdef DEBUG_STRINGHASH
		this->str=inserthashstring(value,str);
#endif
	}

	void make(const char* c)
	{
#ifdef DEBUG_STRINGHASH
		const char* o=c;
#endif
		value=0;
		while (c && (*c))
			value=(value+(*c++))*65599;

#ifdef DEBUG_STRINGHASH
		str=inserthashstring(value,o);
#endif
	}
	void make(const string& s)
	{
		make(s.c_str());
	}

	static stringhash get(const string& s)
	{
		stringhash sh;
		sh.make(s);

		return sh;
	}

	bool operator==(const stringhash& other) const
	{
		return value==other.value;
	}

#ifdef DEBUG_STRINGHASH
	const char* c_str() const
	{
		return str->c_str();
//		return gethashstr(value);
	}
#endif
	/*
	stringhash(const string& s)
	{
		make(s.c_str());
	}
	*/
};